Configuring SameSite Cookies in ASP.NET
TLDR
- The SameSite attribute is used to restrict the sending of third-party cookies to defend against CSRF attacks.
- There are three SameSite values:
None(sent with all requests),Lax(default, sent only with first-party or link requests), andStrict(sent only with first-party requests). - In ASP.NET Core, it is recommended to configure this globally via
CookiePolicyOptionsand implementUser-Agentdetection for older browsers to handleNonevalue compatibility. - In ASP.NET Framework 4.7.2+, global defaults can be set via the
httpCookiesnode inWeb.config. - The SameSite behavior of
ASP.NET_SessionIdis affected by the<sessionState>configuration and requires special attention. - Browser implementations of SameSite vary; compatibility and testing environments (such as using Incognito mode) should be considered during development.
Core Concepts of SameSite Cookies
SameSite is a standard established by the IETF, designed to restrict the transmission of third-party cookies, thereby reducing the risk of Cross-Site Request Forgery (CSRF).
Explanation of Same-Site Attribute Values
| Value | Description |
|---|---|
None | Cookies will be sent with all requests; currently, it must be used with the Secure attribute. |
Lax | The default for modern browsers; sent only in first-party contexts or when the user navigates via a link. |
Strict | Cookies are only sent in requests within a first-party context. |
When do issues occur?
When an application relies on third-party cookies (such as cross-domain iframe embeds or AJAX requests), setting them to Lax or Strict will prevent the cookies from being read correctly, causing user login sessions to fail or features to malfunction.
WARNING
Browser implementations of SameSite are not entirely consistent. Early versions handled unset SameSite attributes differently, and the None value may not be supported in older browsers, requiring fallback handling via User-Agent detection.
Configuring SameSite Cookies in ASP.NET Core
Global Configuration
Control settings globally via CookiePolicyOptions in Program.cs, and ensure app.UseCookiePolicy() is placed before app.UseAuthorization().
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<CookiePolicyOptions>(options => {
// Set the minimum restriction level
options.MinimumSameSitePolicy = SameSiteMode.Unspecified;
// Handle compatibility for older browsers
options.OnAppendCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
options.OnDeleteCookie = cookieContext =>
CheckSameSite(cookieContext.Context, cookieContext.CookieOptions);
});
void CheckSameSite(HttpContext httpContext, CookieOptions options) {
if (options.SameSite == SameSiteMode.None) {
var userAgent = httpContext.Request.Headers["User-Agent"].ToString();
if (DisallowsSameSiteNone(userAgent)) {
options.SameSite = SameSiteMode.Unspecified;
}
}
}Individual Cookie Configuration
If you need to configure specific cookies, you can specify it directly in CookieOptions:
Response.Cookies.Append("name", "value", new CookieOptions() {
SameSite = SameSiteMode.Lax
});Configuring SameSite Cookies in ASP.NET Framework
This feature requires Framework 4.7.2 or higher.
Web.config Global Configuration
If an individual cookie does not specify SameSite, the system will use the default value from httpCookies.
<configuration>
<system.web>
<httpCookies sameSite="Lax"></httpCookies>
</system.web>
</configuration>Compatibility Handling for Older Browsers
Intercept requests in Global.asax.cs and filter out browsers that do not support None:
protected void Application_BeginRequest(object sender, EventArgs e) {
HttpApplication application = sender as HttpApplication;
var userAgent = application.Context.Request.UserAgent;
if (DisallowsSameSiteNone(userAgent)) {
HttpContext.Current.Response.AddOnSendingHeaders(context => {
var cookies = context.Response.Cookies;
for (var i = 0; i < cookies.Count; i++) {
if (cookies[i].SameSite == SameSiteMode.None) {
cookies[i].SameSite = (SameSiteMode)(-1); // Set to Unspecified
}
}
});
}
}TIP
The SameSite setting for ASP.NET_SessionId is typically controlled by <sessionState cookieSameSite="..." /> rather than httpCookies. It is recommended to use Incognito mode during testing to prevent existing cookies from affecting test results.
Change Log
- 2022-10-26 Initial documentation created.